﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace RayTracer
{
    class Data
    {
        public List<Camera> l_cameras;
        public List<Light> l_lights;
        public List<Image> l_images;
        public List<Material> l_materials;
        public List<Triangle> l_triangles;

        private string filePath;
        private StreamReader sr;
        private string line;

        // CONSTRUCTORS
        public Data()
        {
            this.l_cameras = new List<Camera>();
            this.l_lights = new List<Light>();
            this.l_images = new List<Image>();
            this.l_materials = new List<Material>();
            this.l_triangles = new List<Triangle>();
        }

        // METHODS
        public bool LoadScene(string filePath)
        {
            try
            {
                this.filePath = filePath;
                this.sr = new StreamReader(filePath);
                this.line = "";

                while ((this.line = this.sr.ReadLine()) != null)
                {
                    switch (this.line)
                    {
                        case "Camera": ImportCamera();
                            break;
                        case "Image": ImportImage();
                            break;
                        case "Light": ImportLight();
                            break;
                        case "Material": ImportMaterial();
                            break;
                        case "Solid": ImportTriangle();
                            break;
                    }
                }
                return true;
            }
            catch (Exception ex) 
            {
                System.Windows.Forms.MessageBox.Show("Error loading scene: "+ex.ToString());
                return false;
            }
        }

        private void NextLine()
        {
            this.line = this.sr.ReadLine();
        }

        private void ImportCamera()
        {
            NextLine(); NextLine();
            string[] temp_a;
            Camera c = new Camera();
            c.Distance = Double.Parse(this.line.Trim()); NextLine();
            c.Fov = Double.Parse(this.line.Trim()); NextLine();
            temp_a = this.line.Trim().Split(' ');
            Point3D p = new Point3D (Double.Parse(temp_a[0]), Double.Parse(temp_a[1]), Double.Parse(temp_a[2]));
            c.Center = p; NextLine();
            temp_a = this.line.Trim().Split(' ');
            c.HorizontalOrientation = Double.Parse(temp_a[0]);
            c.VerticalOrientation = Double.Parse(temp_a[0]);
            NextLine();
            this.l_cameras.Add(c);
        }

        private void ImportImage()
        {
            NextLine(); NextLine();
            string[] temp_a;
            Image i = new Image();
            this.line = this.line.Replace(".", ",");
            temp_a = this.line.Trim().Split(' ');
            i.HorizontalResolution = Int32.Parse(temp_a[0]);
            i.VerticalResolution = Int32.Parse(temp_a[1]);
            NextLine();
            this.line = this.line.Replace(".", ",");
            temp_a = this.line.Trim().Split(' ');
            Color c = new Color(Double.Parse(temp_a[0]),Double.Parse(temp_a[1]),Double.Parse(temp_a[2]));
            i.BackgroundColor = c;
            NextLine();
            this.l_images.Add(i);
        }

        private void ImportLight()
        {
            NextLine(); NextLine();
            string[] temp_a;
            Light l = new Light();
            this.line = this.line.Replace(".", ",");
            temp_a = this.line.Trim().Split(' ');
            Color c = new Color(Double.Parse(temp_a[0]), Double.Parse(temp_a[1]), Double.Parse(temp_a[2]));
            l.Intensity = c;
            NextLine();
            this.line = this.line.Replace(".", ",");
            temp_a = this.line.Trim().Split(' ');
            Point3D p = new Point3D(Double.Parse(temp_a[0]), Double.Parse(temp_a[1]), Double.Parse(temp_a[2]));
            l.Position = p;
            NextLine();
            this.l_lights.Add(l);
        }

        private void ImportMaterial()
        {
            NextLine(); NextLine();
            string[] temp_a;
            Material m = new Material();
            this.line = this.line.Replace(".", ",");
            temp_a = this.line.Trim().Split(' ');
            Color c = new Color(Double.Parse(temp_a[0]), Double.Parse(temp_a[1]), Double.Parse(temp_a[2]));
            m.Color = c;
            NextLine();
            this.line = this.line.Replace(".", ",");
            temp_a = this.line.Trim().Split(' ');
            m.Ambient = Double.Parse(temp_a[0]);
            m.Diffuse = Double.Parse(temp_a[1]);
            m.Reflection = Double.Parse(temp_a[2]);
            m.Refraction = Double.Parse(temp_a[3]);
            m.Refraction_index = Double.Parse(temp_a[4]);
            NextLine();
            this.l_materials.Add(m);
        }

        private void ImportTriangle()
        {
            NextLine(); NextLine();
            string[] temp_a;
            while (this.line != "}")
            {
                Triangle t = new Triangle();
                t.Material = Int32.Parse(this.line.Trim()); NextLine();
                this.line=this.line.Replace(".", ",");
                temp_a = this.line.Trim().Split(' ');
                Point3D p1 = new Point3D(Double.Parse(temp_a[0]), Double.Parse(temp_a[1]), Double.Parse(temp_a[2]));
                t.FirstVertex = p1;
                NextLine();
                this.line = this.line.Replace(".", ",");
                temp_a = this.line.Trim().Split(' ');
                Point3D p2 = new Point3D(Double.Parse(temp_a[0]), Double.Parse(temp_a[1]), Double.Parse(temp_a[2]));
                t.SecondVertex = p2;
                NextLine();
                this.line = this.line.Replace(".", ",");
                temp_a = this.line.Trim().Split(' ');
                Point3D p3 = new Point3D(Double.Parse(temp_a[0]), Double.Parse(temp_a[1]), Double.Parse(temp_a[2]));
                t.ThirdVertex = p3;
                NextLine();
                this.l_triangles.Add(t);
            }
        }

    }
}
